package cn.texous.web.parsing.book.strategy.search.fiction;

import cn.texous.util.commons.util.ConverterUtils;
import cn.texous.util.commons.util.GsonUtils;
import cn.texous.util.commons.util.HttpUtils;
import cn.texous.util.commons.util.ReplaceUtils;
import cn.texous.web.parsing.book.common.constants.OriginDetailRequestTypeEnum;
import cn.texous.web.parsing.book.common.constants.OriginDetailTypeEnum;
import cn.texous.web.parsing.book.feign.AnaParsingInfo;
import cn.texous.web.parsing.book.model.param.AnaSearchFictionParam;
import cn.texous.web.parsing.book.model.parser.AnaRequestInfo;
import cn.texous.web.parsing.book.model.parser.origin.AnaOriginParser;
import cn.texous.web.parsing.book.model.parser.origin.AnaOriginParserModuleInfo;
import cn.texous.web.parsing.book.model.parser.origin.AnaOriginParserRequestInfo;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

/**
 * insert description here
 *
 * @author Showa.L
 * @since 2019/7/26 10:56
 */
@Component(FictionAnaRequester.FAR)
public class FictionAnaRequester extends AbstractAnaRequester<AnaSearchFictionParam> {

    /**
     * bean name
     */
    public static final String FAR = "fictionAnaRequester";

    @Override
    public AnaParsingInfo getRequestInfo(AnaSearchFictionParam infoParam, AnaOriginParser originParser) {
        AnaOriginParserModuleInfo moduleInfo = originParser
                .getModuleInfoByType(OriginDetailTypeEnum.FICTION);
        AnaOriginParserRequestInfo originParserRequestInfo = moduleInfo
                .getRequestInfoByType(OriginDetailRequestTypeEnum.NORMAL);

        Map<String, String> params = generatorParams(originParserRequestInfo.getParams(),
                ConverterUtils.transBean2StringMap(infoParam));

        String url = originParserRequestInfo.getUrl();
        String body = null;
        if (HttpMethod.GET.name().equals(originParserRequestInfo.getMethod())) {
            if (originParserRequestInfo.getUrlEncoder() != null)
                params = HttpUtils.encoderParams(params,
                        originParserRequestInfo.getUrlEncoder());
            url = HttpUtils.addUrlParams(url, params);
        } else {
            body = GsonUtils.toJson(params);
        }

        AnaRequestInfo requestInfo = AnaRequestInfo.builder()
                .body(body)
                .headers(originParser.getBaseInfo().getCustomizeHeader())
                .method(originParserRequestInfo.getMethod())
                .url(url)
                .build();

        addHttpCharset(originParserRequestInfo, requestInfo, originParser.getBaseInfo());

        AnaParsingInfo parsingInfo = new AnaParsingInfo();
        parsingInfo.setRespType(originParser.getBaseInfo().getRespType());
        parsingInfo.setRequestInfo(requestInfo);
        parsingInfo.setParsingFieldInfos(moduleInfo.getAnaFieldInfos());

        return parsingInfo;
    }

    private Map<String, String> generatorParams(Map<String, String> regexParams,
                                                Map<String, String> replaceParams) {
        Map<String, String> keyMap = Optional.ofNullable(replaceParams)
                .map(rp -> ReplaceUtils.toRegexKeyMap(rp,
                        ReplaceUtils.DOLLAR_PARENTHESIS_START, ReplaceUtils.PARENTHESIS_END))
                .orElse(new HashMap<>());
        return Optional.ofNullable(regexParams)
                .map(Map::entrySet)
                .map(entries -> {
                    Map<String, String> result = new HashMap<>();
                    entries.forEach(e -> {
                        String value = keyMap.get(e.getValue());
                        result.put(e.getKey(), value == null ? e.getValue() : value);
                    });
                    return result;
                }).orElse(new HashMap<>());
    }

}
